import ValuePair from "./valuePair";
import type { IDictionary } from "../types";

/**
 * #### 判断一个值是否为空
 * @param value 传入的值
 * @param option 传入的选项，包括是否为空字符串和是否为零数字
 * @returns
 */
function isEmpty(
  // 传入的值
  value: any,
  // 传入的选项，包括是否为空字符串和是否为零数字
  option: {
    emptyString: boolean | undefined;
    zeroNumber: boolean | undefined;
  } = { emptyString: false, zeroNumber: false }
): boolean {
  // 如果值为null或undefined，则判断是否为空字符串或零数字
  if (value === null || value === undefined) {
    return !(
      (option.emptyString && value === "") ||
      (option.zeroNumber && value === 0)
    );
  }
  // 否则返回false
  return false;
}

class Dictionary<K, V> implements IDictionary<K, V> {
  table: ValuePair<K, V>[];
  constructor() {
    this.table = [];
  }

  private getItemIndex(key: K): number {
    for (let i = 0, len = this.table.length; i < len; i++) {
      if (this.table[i].key === key) {
        return i;
      }
    }
    return -1;
  }

  set(key: K, value: V): void {
    if (isEmpty(key)) {
      throw new Error("key is required");
    }
    if (isEmpty(value)) {
      throw new Error("value is required");
    }
    if (this.has(key)) {
      let index = this.getItemIndex(key);
      this.table[index].value = value;
    } else {
      const new_node = new ValuePair(key, value);
      this.table.push(new_node);
    }
  }

  remove(key: K): ValuePair<K, V> | undefined {
    if (this.has(key)) {
      let index = this.getItemIndex(key);
      return this.table.splice(index, 1)[0];
    }
    return undefined;
  }

  has(key: K): boolean {
    return this.getItemIndex(key) !== -1;
  }

  get(key: K): ValuePair<K, V> | undefined {
    if (this.has(key)) {
      let index = this.getItemIndex(key);
      return this.table[index];
    }
    return void 0;
  }

  keys(): K[] {
    return this.table.map((item) => item.key);
  }

  values(): V[] {
    return this.table.map((item) => item.value);
  }

  keyValues(): Array<[K, V]> {
    return this.table.map((item) => [item.key, item.value]);
  }

  forEach(callbackFunc: (key: K, value: V) => boolean | void): void {
    for (let i = 0, len = this.size(); i < len; i++) {
      let item = this.table[i];
      let flag = callbackFunc(item.key, item.value);
      if (!flag) {
        break;
      }
    }
  }

  isEmpty(): boolean {
    return !this.size();
  }

  size(): number {
    return this.table.length;
  }

  clear(): void {
    this.table = [];
  }

  toString(): string | null {
    let result = "";
    for (let i = 0, len = this.table.length; i < len; i++) {
      result += this.table[i].toString();
      result += ",";
    }
    result = result.slice(0, -1);
    return result;
  }
}

export default Dictionary;
